/*
 * Amkai Enterprise Solution (AES.) 
 * Copyright 2004 by Amkai(TM), Inc.
 * www.amkai.com
 * 
 * Project: webservice
 * Package: com.amkai.aes.webservice.binary.objecthandler.scheduler
 * File: AvailableResourcesConflictCheckingHanlder.java
 * Created: 2010.09.23. 10:38:35
 * Author: Keri Kornel (keri.kornel)
 * 
 */

/**
 * 
 */
package com.amkai.aes.webservice.binary.objecthandler.scheduler;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.amkai.aes.aescommon.factory.RADBeanFactory;
import com.amkai.aes.aescommon.schedule.SchedulingTransientPropertyNames;
import com.amkai.aes.aescommon.service.binary.job.schedule.AvailableResourcesConflictCheckingJob;
import com.amkai.aes.aescommon.service.result.schedule.AvailableResourcesConflictCheckingResult;
import com.amkai.aes.aescommon.service.scheduling.CheckResult;
import com.amkai.aes.generatedbeans.scheduling.AbstractAppointment;
import com.amkai.aes.generatedbeans.scheduling.AppointmentRelation;
import com.amkai.aes.generatedbeans.scheduling.Reservation;
import com.amkai.aes.generatedbeans.scheduling.ResourceConnection;
import com.amkai.aes.generatedbeans.scheduling.SchedulingResource;
import com.amkai.aes.generatedbeans.scheduling.resources.AppointmentType;
import com.amkai.aes.server.conflict.scheduling.ServerSchedulingValidator;
import com.amkai.aes.webservice.binary.JobObjectHandler;
import com.amkai.common.extensions.hibernate.config.SiteManager;
import com.amkai.common.extensions.hibernate.config.manager.SessionManager;

/**
 * @author KeriKornel
 *
 */
// KKORNEL: AES-13957
public class AvailableResourcesConflictCheckingHanlder implements JobObjectHandler<AvailableResourcesConflictCheckingJob, Serializable, AvailableResourcesConflictCheckingResult> {
	//static int a = 0; 
	@Override
	public AvailableResourcesConflictCheckingResult process(AvailableResourcesConflictCheckingJob job, Serializable object) throws Exception {
		AvailableResourcesConflictCheckingResult result = new AvailableResourcesConflictCheckingResult();
		SessionManager sm = null;
		try {
			Set<Long> resourceIds = job.getResourcesToCheckId();
			if ((resourceIds.size() > 0) && (job.getAppointmentTypeId() != null) && (job.getBeginTimeToCheck() != null) && (job.getEndTimeToCheck() != null)) {
				sm = SiteManager.Start();
				AbstractAppointment abstractAppointment = RADBeanFactory.getInstance().createBean(AbstractAppointment.class);
				abstractAppointment.setId(job.getCurrentAppointmentId());
				AppointmentType appointmentType = (AppointmentType) sm.execute("FROM AppointmentType WHERE id = :id").setLong("id", job.getAppointmentTypeId()).uniqueResult();
				abstractAppointment.setAppointmentType(appointmentType);
				if (job.getMainAppointmentId() != null) {
					AbstractAppointment mainAppointment = (AbstractAppointment) sm.execute("FROM AbstractAppointment WHERE id = :id").setLong("id", job.getMainAppointmentId()).uniqueResult();
					AppointmentRelation appointmentRelation = RADBeanFactory.getInstance().createBean(AppointmentRelation.class);
					appointmentRelation.setOwnerAppointment(mainAppointment);
					if (abstractAppointment.getAppointmentRelations() == null) {
						abstractAppointment.setAppointmentRelations(new HashSet<AppointmentRelation>());
					}
					abstractAppointment.getAppointmentRelations().add(appointmentRelation);
				}
				abstractAppointment.putTranzientProperty(SchedulingTransientPropertyNames.BEGIN_TIME_FOR_CONFLICT, job.getBeginTimeToCheck());
				abstractAppointment.putTranzientProperty(SchedulingTransientPropertyNames.END_TIME_FOR_CONFLICT, job.getEndTimeToCheck());
				List<Long> resourceIdsToRemove = new ArrayList<Long>();
				ResourceConnection rc = RADBeanFactory.getInstance().createBean(ResourceConnection.class);
				Reservation res = RADBeanFactory.getInstance().createBean(Reservation.class);
				rc.setReservation(res);
				abstractAppointment.putTranzientProperty(SchedulingTransientPropertyNames.TARGET_RESOURCECONNECTION, rc);
				for (Long resourceId : resourceIds) {
					SchedulingResource target = (SchedulingResource) sm.execute("FROM SchedulingResource WHERE id = :id").setLong("id", resourceId).uniqueResult();
					res.setSchedulingResource(target);
					Collection<CheckResult> overbooks = ServerSchedulingValidator.checkAppointmentOverbook(sm, job.getModuleDepartment(), abstractAppointment, new ArrayList<CheckResult>());
					if ((overbooks != null) && (overbooks.size() > 0)) {
						resourceIdsToRemove.add(resourceId);
					}
					
				}
				for (Long resourceIdToRemove : resourceIdsToRemove) {
					resourceIds.remove(resourceIdToRemove);
				}
			}
			result.setValidResourceIds(resourceIds);
		} finally {
			if (sm != null) {
				sm.closeSession();
			}
		}
		return result;
	}

}
